package files;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;

import polarity.Polarity;

import classifier.Classifier;
import classifier.ClassifierManager;

import UI.JFrame;

import tools.Normalizer;

public class Tweet 
{
	private static Integer count = 0;
	private String type; // polarite
	private String mark;
	private String content;
	
	private Classifier classifierMark;
	
	private TreeMap<String, Integer> vocabulary;
	
        /**
         * Retourne l'id du tweet
         * @return 
         */
	public Integer getId() { return count; }
        /**
         * Retourne la polarite du tweet
         * @return 
         */
	public String getType() { return type; }
        /**
         * Retourne la marque du tweet
         * @return 
         */
	public String getMark() { return mark; }
        /**
         * Modifie la marque du tweet
         * @param mark marque
         */
	public void setMark(String mark) { this.mark = mark; }
        /**
         * Renvoie le contenu du tweet
         * @return 
         */
	public String getContent() { return content; }
        /**
         * Renvoie le vocabulaire du tweet
         * @return 
         */
	public TreeMap<String, Integer> getVocabulary() { return vocabulary; }
	
	
	private Hashtable<String,Double> bayesBinomialHt = new Hashtable<String,Double>();
	private Hashtable<String,Double> bayesMultinomialHt = new Hashtable<String,Double>();
	
        /**
         * Retourne le calcul binomial du tweet
         * @return 
         */
	public Hashtable<String, Double> getBayesBinomialHt() { return bayesBinomialHt; }
        /**
         * Retourne le calcul multinomial du tweet
         * @return 
         */
	public Hashtable<String, Double> getBayesMultinomialHt() { return bayesMultinomialHt; }
	
	
//	prior
//	aPriori
//	vraisemblance
//	test
	
	//prior = aPriori * vraisemblance / test;
	/**
         * Mofidie le classifieur associe
         * @param classifier le nouveau classifieur
         */
	public void setClassifierMark(Classifier classifier)
	{
		classifierMark = classifier;
	}
	
        /**
         * Constructeur
         * @param type polarite du tweet
         * @param mark marque du tweet
         * @param content contenu du tweet
         * @param normalizer normalizer a utiliser
         */
	public Tweet(String type, String mark, String content, Normalizer normalizer)
	{
		this.count = count;
		count++;
		this.type = type;
		this.mark = mark;
		this.content = content;
		vocabulary = new TreeMap<String, Integer>();
		
		bayesBinomialHt.put("positive", 0.0);
		bayesBinomialHt.put("negative", 0.0);
		bayesBinomialHt.put("neutral", 0.0);
		bayesBinomialHt.put("irrelevant", 0.0);
		
		bayesMultinomialHt.put("positive", 0.0);
		bayesMultinomialHt.put("negative", 0.0);
		bayesMultinomialHt.put("neutral", 0.0);
		bayesMultinomialHt.put("irrelevant", 0.0);
		
		
		 try 
		 { 
			String newContent = "";
			if ( JFrame.optStopWordIsOn() == true)
		 	{
				
				for (String word : normalizer.normalize(content)) 
				 {
			 
				 	TreeMap<String, Integer> stopWord = ClassifierManager.getStopWord();
				 	word = word.toLowerCase();
			 		if ( stopWord.containsKey(word) == false )
			 		{
			 			addWord(word);
			 			newContent += word+" ";
			 		}
				 }
		 	}
			else
			{
				 for (String word : normalizer.normalize(content)) 
				 {		 	
					 word = word.toLowerCase();
					 addWord(word);
					 newContent += word+" ";
			    }
			}
			this.content = newContent;
		} 
		catch (IOException e) 
		{
			e.printStackTrace();
		}
		
		
	}

        /**
         * Ajoute un mot au vocabulaire du tweet
         * @param word le mot a ajouter
         */
	private void addWord(String word)
	{
		 if (vocabulary.containsKey(word)) 
         {
            
         	int count = vocabulary.get(word);
         	count++;
             vocabulary.put(word, count);
             
         } 
         else 
         {    	
             vocabulary.put(word, 1);
         }
	}
	
        /**
         * Retourne le nombre de mots que contient le tweet
         * @return 
         */
	public Integer getNumberOfWords()
	{
		int numberOfWords = 0;
		for (Map.Entry<String, Integer> set : vocabulary.entrySet() ) 
		{
			numberOfWords += set.getValue();
		}
		return numberOfWords;
	}
	
        /**
         * Retourne la taille du tweet en nombre de caracteres
         * @return 
         */
	public int getTweetSize()
        {
            return content.length();
        }
	
        /**
         * Retourne le nombre de mots differents dans le tweet
         * @return 
         */
	public Integer getNumberOfDifferentWords()
	{
		return vocabulary.size();
	}
	
        /**
         * Effectue la prediction
         * @param ht le classifieur a utiliser
         */
	public void choiceResultat(Hashtable<String, Double> ht)
	{
		Double bayesMax = Double.NEGATIVE_INFINITY;
		
		String typeName = "irrelevant";
		
		for(Entry<String, Double> entryBayes : ht.entrySet() )
		{
			if ( bayesMax < entryBayes.getValue() )
			{
				bayesMax = entryBayes.getValue();
				typeName = entryBayes.getKey();
				
				
			}
		}
		type = typeName;
	}
	
	/**
         * type de methode a utiliser pour le calcul
         */
	public void useMethod()
	{
		switch( TweetManager.getMethod())
		{
			case "binomial": useMethodBinomial();choiceResultat(bayesBinomialHt); break;
			case "multinomial": useMethodMultinomial(); choiceResultat(bayesMultinomialHt); break;
			case "cluster": useMethodCluster();  break;
			case "moyenne": useMethodAverage(); break;
			default: break; 
		}	
	}
	
	/**
         * utilise la methode de calcul binomial
         */
	public void useMethodBinomial()
	{
		String[] words = content.split(" ");
		Hashtable<String, Polarity> polarityHt = classifierMark.getPolarityManager().getPolarityHt();
		TreeMap<String, Integer> vocabulary = ClassifierManager.getClassifierHt().get("general").getVocabularyGeneral();
		
			for(Entry<String, Polarity> entryPolarity : polarityHt.entrySet() )
			{
				Double bayes = bayesBinomialHt.get(entryPolarity.getKey());
				TreeMap<String, Double> baynesPolarity = entryPolarity.getValue().getBayesBinomial();
				TreeMap<String, Integer> baynesPolarityVocabulary = entryPolarity.getValue().getVocabulary();
				bayes =  Math.log(1.00);
				
			//	for(int i=0;i<words.length;i++)
			//	{
				for(Entry<String, Integer> entryVocabulary : vocabulary.entrySet() )
				{	
					if ( baynesPolarity.containsKey(entryVocabulary.getKey()))
					{
						boolean trouve = false;
						for(int i=0;i<words.length;i++)
						{
							if ( words[i].compareTo(entryVocabulary.getKey()) == 0)
							{
								trouve = true;
								break;
							}
						}
						if ( trouve == true ) 
						{
							if ( baynesPolarityVocabulary.containsKey(entryVocabulary.getKey())  )
							{
								// Puissance
								for(int j=0;j<baynesPolarityVocabulary.get(entryVocabulary.getKey());j++)
								{
									bayes += Math.log(baynesPolarity.get(entryVocabulary.getKey()));
									
								}
							}	
						}
						else  bayes += Math.log(1-baynesPolarity.get(entryVocabulary.getKey()));
					}
					else 
					{
						bayes += Math.log(0.01);
					}
					
				}
				
				bayesBinomialHt.put(entryPolarity.getKey(), bayes);
			}
	}
	
        /**
         * utilise la methode de calcul multinomial
         */
	public void useMethodMultinomial()
	{
		String[] words = content.split(" ");
	
		Hashtable<String, Polarity> polarityHt = classifierMark.getPolarityManager().getPolarityHt();
		// Pour chaque Polarite
		for(Entry<String, Polarity> entryPolarity : polarityHt.entrySet() )
		{
			Double bayes = bayesMultinomialHt.get(entryPolarity.getKey());
			TreeMap<String, Double> baynesPolarity = entryPolarity.getValue().getBayesMultinomial();
			bayes = (Double) Math.log((double) entryPolarity.getValue().getNumberOfTweet()/(double)classifierMark.getPolarityManager().getNumberOfTweet());
			//double test = ((double)entryPolarity.getValue().getNumberOfTweet()/(double)classifierMark.getPolarityManager().getNumberOfTweet());
		

			for(int i=0;i<words.length;i++)
			{
				if ( baynesPolarity.containsKey(words[i]) )
				{
					//baynes += (float)Math.log(baynesPolarity.get(words[i]));
					bayes += (float)Math.log(baynesPolarity.get(words[i]));
					
					
					//System.out.println(baynes+" - w "+words[i]);
				}
				else // Mot qui n'a pas �t� vu durant le training
				{
					//baynes += (float)Math.log((float) 1/(classifierMark.getPolarityManager().getPolarityHt().get(entryPolarity.getKey()).getNumberOfWords()+classifierMark.getPolarityManager().getNumberOfDifferentWords()));
				}
				
				
				
			}
			//System.out.println(baynes);
		
			bayesMultinomialHt.put(entryPolarity.getKey(), bayes);
		}
	}
	
        /**
         * utilise la methode de calcul du cluster
         */
	public void useMethodCluster()
	{
		
	}
	
        /**
         * utilise la methode de calcul de la moyenne
         */
	public void useMethodAverage()
	{
		
	} 
	
}
